#pragma once

// #include "ScriptControl.h"
#include "atlbase.h"
#include "dispex.h"
#include "deque"
#include "dispex.h"
#include "mshtml.h"
#include "comutil.h"

class CScriptObject
{
public:
	CScriptObject(IWebBrowser2* pWeb);
	CScriptObject(IWebBrowser2* pWeb, IDispatch* pDisp);
	
	IDispatch* GetDispatch() const;
	IDispatchEx* GetDispatchEx() const;
	
// 	operator IDispatch* () const
// 	{
// 		return m_spDisp;
// 	}
// 
// 	operator IDispatchEx* () const
// 	{
// 		return m_spDisp;
// 	}
	
	operator _variant_t() const
	{
		_variant_t(m_spDisp);
	}
	
	CScriptObject CreateScriptObject();
	CComPtr<IWebBrowser2> GetWebBrowser();
public:
	BOOL GetValue(BSTR bstrKey, _variant_t& vRet);

	template<class T>
	BOOL GetValue(BSTR bstrKey, T* pValue)
	{
		try
		{
			_variant_t v;
			if (GetValue(bstrKey, v))
			{
				*pValue = v;
				return TRUE;
			}
		}
		catch (...)
		{
		}
		return FALSE;
	}
	
	BOOL SetValue(BSTR bstrKey, _variant_t& vValue);

	BOOL DeleteValue(BSTR bstrKey);
	void DeleteAllValues();

	CComPtr<IDispatchEx> CreateObject();
// 	template<class T>
// 	void SetValue(BSTR bstrKey, T pValue)
// 	{
// 		s_GetScriptControl().Run(lpszKey, m_pDisp, pValue);
// 	}

	template<typename TFun>
	void ForEach(TFun fun)
	{
		DISPID dispID = DISPID_STARTENUM;
		CComBSTR bstrName;
		HRESULT hr;
		while (true)
		{
			hr = m_spDisp->GetNextDispID(fdexEnumAll, dispID, &dispID);
			if (SUCCEEDED(hr) && dispID != DISPID_UNKNOWN)
			{
				m_spDisp->GetMemberName(dispID, &bstrName);
				fun(bstrName);
				continue;
			}
			break;
		}
	}

	std::deque<CComBSTR> GetAllMembers();
	
private:
	CComQIPtr<IDispatchEx> m_spDisp;
	CComPtr<IWebBrowser2> m_spWeb;
};